#pragma once

#include"TcpServer.hpp"
#include"HttpProtocol.hpp"
using http_handle_t = std::function<void(HttpRequest&,HttpResponse&)>;

class HttpServer{
    public:
        HttpServer(int port)
            :_tcp_server(std::make_unique<TcpServer>(port))
        {}
        void Resgister(const std::string &uri,http_handle_t handle)//注册路由:将URI和处理函数绑定
        {
            _route[uri] = handle;
        }
        bool SafeCheck(const std::string &service)
        {
            return _route.find(service)!= _route.end();
        }
        void Start()//启动服务:传递解决请求方法，创建套接字一系列操作
        {
            _tcp_server->InitServer([this](SockPtr socket, struct sockaddr* addr){
                return this->HandleHttpRequest(socket, addr);
            });
            _tcp_server->Loop();
        }
        bool HandleHttpRequest(SockPtr sock, struct sockaddr* addr)//处理请求:解析请求报文，构造响应报文，发送响应报文
        {
            //获取客户端IP地址和端口号
            struct sockaddr_in* client_addr = (struct sockaddr_in*)addr;
            uint16_t client_port = ::ntohs(client_addr->sin_port);
            char buffer[64];
            std::string client_ip = ::inet_ntop(AF_INET,&client_addr->sin_addr,buffer,sizeof(buffer));//将IP地址转换为字符串
            LOG(log_level::INFO)<<"HttpServer: get a new client "<<sock->Fd()<<" from "<<client_ip<<":"<<client_port;
           
            std::string http_request;//收到的请求报文
            sock->Recv(&http_request);
            HttpRequest req;//请求报文对象
            req.Deserialize(http_request);//反序列化处理请求报文,填充req对象
            HttpResponse resp;//响应报文对象
            
            
            //反序列化后请求应该分为两类:1、请求一般的静态资源  2、提交参数，携带参数，需要我们交互设置
            if(req.HasArgs()){//如果请求携带参数，则交互设置
                std::string service = req.Path();
                if(SafeCheck(service))//如果请求的URI存在于路由表中
                    _route[req.Path()](req,resp);//交互设置，并调用对应的处理函数
                else{//如果请求的URI不存在于路由表中
                    resp.BuildResponse(req);//构造响应报文，返回404错误
                }
            }else{//如果请求一般的静态资源，则直接构造响应报文
                resp.BuildResponse(req);
            }
            
            
            // req.Print();
            std::string http_response;//返回的响应报文
            resp.Serialize(&http_response);//序列化构造响应报文
            sock->Send(http_response);
            
            return true;
        }
    private:
        std::unique_ptr<TcpServer> _tcp_server;
        std::unordered_map<std::string,http_handle_t> _route;//路由表，根据请求的URI，找到对应的处理函数

};


